package de.fhluebeck.oop.gps.service.impl;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.fhluebeck.oop.gps.common.Constants;
import de.fhluebeck.oop.gps.common.DependencyManager;
import de.fhluebeck.oop.gps.common.Singleton;
import de.fhluebeck.oop.gps.common.exception.DatabaseStateException;
import de.fhluebeck.oop.gps.dao.IDAO;
import de.fhluebeck.oop.gps.db.Database;
import de.fhluebeck.oop.gps.service.IDatabaseService;

/**
 * Implementation des Interfaces für den Database-Service.
 * @author Ogün Bilge, Leif Hitzschke
 * @version 1.00, 13.11.2009
 * 
 */
public class DatabaseServiceImpl implements IDatabaseService, Singleton {
	private final static Logger log = LoggerFactory
			.getLogger(DatabaseServiceImpl.class);

	private DatabaseServiceImpl() {
	}

	// Holder Idiom Pattern
	private static class Holder {
		private static final DatabaseServiceImpl instance = new DatabaseServiceImpl();
	}

	public static IDatabaseService getInstance() {
		return Holder.instance;
	}

	private Database database;
	private List<IDAO<?>> registeredDAOs;

	private void checkHealth() throws SQLException {
		// check database
		log.debug("checking health");
		for (IDAO<?> dao : registeredDAOs) {
			if (!dao.isValid()) {
				dao.initialize();
			}
		}

	}

	private void cleanup() {
		try {
			for (IDAO<?> dao : registeredDAOs) {
				if (dao.isValid()) {
					dao.drop();
				}
			}
		} catch (SQLException e) {
			log.debug("Could not initialize Database!");
			throw new DatabaseStateException(e);
		}
	}

	private void initialize() {

		database = (Database) DependencyManager
				.locate(Constants.DATABASE_DEP_NAME);
		database.initialize();
		
		registeredDAOs = new ArrayList<IDAO<?>>();
		registeredDAOs.add((IDAO<?>) DependencyManager
				.locate(Constants.CATEGORY_DEP_NAME));
		registeredDAOs.add((IDAO<?>) DependencyManager
				.locate(Constants.POI_DEP_NAME));

		
		for (IDAO<?> dao : registeredDAOs) {
			dao.setDatabase(database);
		}

	}

	@Override
	public Connection getConnection() throws SQLException {
		return database.getConnection();
	}

	@Override
	public void initDatabase() {
		try {
			initialize();
			checkHealth();
		} catch (SQLException e) {
			log.debug("Could not initialize Database!");
			throw new DatabaseStateException(e);
		}

	}

}
